IF OBJECT_ID('dbo.Swieta') IS NOT NULL
	DROP TABLE dbo.Swieta;
GO

CREATE TABLE dbo.Swieta
(
	Data DATETIME
)
GO

IF OBJECT_ID('dbo.Zgloszenia') IS NOT NULL
	DROP TABLE dbo.Zgloszenia;
GO

CREATE TABLE dbo.Zgloszenia
(
	Nr_zgloszenia INT NOT NULL IDENTITY PRIMARY KEY,
	Opis_problemu VARCHAR(1000) NOT NULL,
	Odpowiedx VARCHAR(1000),
	Osoba_zglaszajaca VARCHAR(60) NOT NULL,
	Data_zgloszenia DATETIME NOT NULL,
	Data_zakonczenia DATETIME NOT NULL,
	Osoba_konczaca VARCHAR(60) NOT NULL,
	Grupa_administratorow VARCHAR(60) NOT NULL,
	Teoretyczny_czas_wykonania DATETIME  NOT NULL,
	Priorytet VARCHAR(10) NOT NULL,  
	Kategoria VARCHAR(10) NOT NULL,
)



-- jeli istnieje funkcja ...
IF OBJECT_ID('dbo.Licz_opoznienia_wg_teoretycznego_czasu') IS NOT NULL
DROP FUNCTION dbo.Licz_opoznienia_wg_teoretycznego_czasu; -- ... to j usuwamy
GO

-- tworzymy now funkcj z parametrami
CREATE FUNCTION dbo.Licz_opoznienia_wg_teoretycznego_czasu 
-- czas zakoczenia zgoszenia
(@p_czas_zakonczenia DATETIME, 
-- czas do kiedy zgoszenie powinno by zakoczone
@p_teoretyczny_czas  DATETIME, 
-- pocztek roboczych godzin pracy
@p_godzina_od        INT,      
-- koniec roboczych godzin pracy
@p_godzina_do        INT)      
RETURNS INT -- funkcja zwrci warto typu INT
-- ustawianie rekomendowanych opcji funkcji
WITH SCHEMABINDING, RETURNS NULL ON NULL INPUT
AS
BEGIN

	DECLARE 
		-- ilo dni roboczych midzy faktycznym, 
		-- a teoretycznym czasem zakoczenia zgoszenia
		@ilosc_dni   INT,
		-- ilo dni (z sobotami niedzielami i witami) 
		-- midzy faktycznym a teoretycznym czasem zakoczenia zgoszenia
		@roznica_dni INT, 
		@ilosc_minut INT, -- ilo minut przeterminowania
		@pomoc_czas  DATETIME; -- zmienna pomocnicza

        -- obliczanie ile dni mino midzy teoretycznym czasem 
	-- zamknicia zgoszenia,a faktycznym zamkniciem
	-- cznie ze witami, sobotami i niedzielami
	SET @roznica_dni = DATEDIFF(day, @p_teoretyczny_czas, @p_czas_zakonczenia)

	-- ustawienie pocztkowych wartoci
	SET @ilosc_minut = 0;
	SET @ilosc_dni   = 0;
	SET @pomoc_czas  = @p_teoretyczny_czas;

	-- gdy godzina zakoczenia zgoszenia jest wiksza od godziny_do
	IF DATEPART(hour, @p_czas_zakonczenia) >= @p_godzina_do
	BEGIN
		-- to aktualizowana jest godzina w dacie zakoczenia zgoszenia
		-- na godzina_do
		SET @p_czas_zakonczenia = CAST(CAST(DATEPART(year, @p_czas_zakonczenia) 
AS VARCHAR) + RIGHT('0' + CAST(DATEPART(month, @p_czas_zakonczenia) 
AS VARCHAR), 2) + RIGHT('0' + CAST(DATEPART(day, @p_czas_zakonczenia) 
AS VARCHAR), 2) + ' ' + RIGHT('0' + CAST(@p_godzina_do AS VARCHAR), 2) 
+ ':00:00' AS DATETIME);
	END;
	-- gdy czas zakoczenia jest mniejszy od godziny_od
	IF DATEPART(hour, @p_czas_zakonczenia) < @p_godzina_od
	BEGIN
		-- to aktualizowana jest godzina w dacie zakoczenia zgoszenia
		-- na godzina_od
		SET @p_czas_zakonczenia = CAST(CAST(DATEPART(year, @p_czas_zakonczenia) 
AS VARCHAR) + RIGHT('0' + CAST(DATEPART(month, @p_czas_zakonczenia) 
AS VARCHAR), 2) + RIGHT('0' + CAST(DATEPART(day, @p_czas_zakonczenia) 
AS VARCHAR), 2) + ' ' + RIGHT('0' + CAST(@p_godzina_od AS VARCHAR), 2) 
+ ':00:00' AS DATETIME);
	END;
	
	-- gdy rnica dni midzy czasem zakoczenia a teoretycznym czasem zakoczenia
	-- wynosi 0 dni ...
	IF @roznica_dni = 0
	BEGIN
		-- i jeli przegldany dzie jest witem ...
		IF (((SELECT COUNT(*) FROM dbo.Swieta WHERE data = CAST(CAST(DATEPART(year, 
@pomoc_czas) AS VARCHAR) + RIGHT('0' + CAST(DATEPART(month, @pomoc_czas) 
AS VARCHAR), 2) + RIGHT('0' + CAST(DATEPART(day, @pomoc_czas) 
AS VARCHAR), 2) + ' 00:00:00' AS DATETIME))> 0)
			-- ... lub jeli jest sobot ...
			OR (DATEPART(dw, @pomoc_czas) = 7) 
			-- ... lub jeli jest niedziela ...
			OR (DATEPART(dw, @pomoc_czas) = 1))
		BEGIN
			-- to ustawiana jest liczba minut opnienia na 0
			SET @ilosc_minut = 0;
		END
		-- ... w przeciwnym wypadku ...
		ELSE
		BEGIN
			-- liczona jest rnica minut pomidzy teoretycznym czasem zakoczenia 
			-- a faktycznym czasem zakoczenia
			SET @ilosc_minut = DATEDIFF(minute, @p_teoretyczny_czas, 
@p_czas_zakonczenia);
		END
	END;

	-- gdy rnica midzy teoretycznym czasem zakoczenia
	-- a faktycznym czasem zakoczenia jest wiksza ni 1 dzie
	-- od rnicy odejmowany jest jeden dzie
	SET @roznica_dni = @roznica_dni - 1; 

	IF @roznica_dni >= 0
	BEGIN
		-- dopki rnica_dni jest wiksza od zera
		WHILE @roznica_dni > 0
		BEGIN
			-- zwikszana jest data o jeden dzie
			SET @pomoc_czas = @pomoc_czas + '19000102 00:00:00';
		
			-- i nastpuje sprawdzenie czy dany dzie ...
		    	-- NIE jest witem
			IF (((SELECT COUNT(*) FROM dbo.Swieta WHERE data = 
CAST(CAST(DATEPART(year, @pomoc_czas) AS VARCHAR) + 
				RIGHT('0' + CAST(DATEPART(month, @pomoc_czas) AS VARCHAR), 2) + 
				RIGHT('0' + CAST(DATEPART(day, @pomoc_czas) AS VARCHAR), 2) + 
				' 00:00:00' AS DATETIME)) = 0)
				-- i NIE jest sobot
				AND (DATEPART(weekday, @pomoc_czas) <> 7) 
				-- i NIE jest niedziel
				AND (DATEPART(weekday, @pomoc_czas) <> 1))
			BEGIN
				-- to zwikszana jest liczba penych dni roboczych
				SET @ilosc_dni = @ilosc_dni + 1
			END
	
			-- zmniejszenie licznika ptli
			SET @roznica_dni = @roznica_dni - 1;
		END;

		-- obliczenie iloci minut roboczych pomidzy 
		-- teoretycznym czasem realizacji,
		-- a faktycznym czasem realizacji
		-- najpierw liczona jest ilo minut penych dni roboczych
		SET @ilosc_minut =  @ilosc_dni  * (@p_godzina_do - @p_godzina_od) * 60 
			-- nastpnie dodawana jest liczba minut pomidzy 
			-- teoretycznym czasem realizacji a kocow godzin tego samego dnia
			-- pod warunkiem, e nie jest to sobota, niedziela i wito ...
		+ CASE WHEN (SELECT COUNT(*) FROM dbo.Swieta WHERE data = 
			CAST(CAST(DATEPART(year, @p_teoretyczny_czas) AS VARCHAR) + 
			RIGHT('0' + CAST(DATEPART(month, @p_teoretyczny_czas) AS VARCHAR), 2) + 
			RIGHT('0' + CAST(DATEPART(day, @p_teoretyczny_czas) AS VARCHAR), 2) + 
			' 00:00:00' AS DATETIME)) > 0 THEN 0
		     WHEN DATEPART(dw, @p_teoretyczny_czas) = 7 THEN 0
		     WHEN DATEPART(dw, @p_teoretyczny_czas) = 1 THEN 0
		     ELSE
			DATEDIFF( minute,
			CAST(CAST(DATEPART(year, @p_teoretyczny_czas) AS VARCHAR) + RIGHT('0' + 
			CAST(DATEPART(month, @p_teoretyczny_czas) AS VARCHAR), 2) + 
			RIGHT('0' + CAST(DATEPART(day, @p_teoretyczny_czas) AS VARCHAR), 2) + 
' ' + 
			RIGHT('0' + CAST(DATEPART(hour, @p_teoretyczny_czas) AS VARCHAR), 2) + 
':' +
RIGHT('0' + CAST(DATEPART(minute, @p_teoretyczny_czas) AS VARCHAR), 2) + 
':00' AS DATETIME),
			CAST(CAST(DATEPART(year, @p_teoretyczny_czas) AS VARCHAR) + RIGHT('0' + 
			CAST(DATEPART(month, @p_teoretyczny_czas) AS VARCHAR), 2) + 
			RIGHT('0' + CAST(DATEPART(day, @p_teoretyczny_czas) AS VARCHAR), 2) + 
' ' + 
			RIGHT('0' + CAST(@p_godzina_do AS VARCHAR), 2) + ':00:00' 
			AS DATETIME) 
			)
		END
		+
		-- nastpnie dodawana jest liczba minut od pocztku dnia
		-- do godziny zakoczenia
		-- pod warunkiem, e nie jest to sobota, niedziela i wito ...
		CASE WHEN (SELECT COUNT(*) FROM dbo.Swieta WHERE data = 
			CAST(CAST(DATEPART(year, @p_czas_zakonczenia) AS VARCHAR) + 
			RIGHT('0' + CAST(DATEPART(month, @p_czas_zakonczenia) AS VARCHAR), 2) + 
			RIGHT('0' + CAST(DATEPART(day, @p_czas_zakonczenia) AS VARCHAR), 2) + 
			' 00:00:00' 
			AS DATETIME)) > 0 THEN 0
		     WHEN DATEPART(dw, @p_czas_zakonczenia) = 7 THEN 0
		     WHEN DATEPART(dw, @p_czas_zakonczenia) = 1 THEN 0
		     ELSE
			 CASE
			-- jeli ta rnica jest mniejsza od 0, to zamieniana jest na 0
			 WHEN
				DATEDIFF( minute,
				CAST(CAST(DATEPART(year, @p_czas_zakonczenia) AS VARCHAR) + 
RIGHT('0' + 					
CAST(DATEPART(month, @p_czas_zakonczenia) AS VARCHAR), 2) + 
				RIGHT('0' + CAST(DATEPART(day, @p_czas_zakonczenia) 
AS VARCHAR), 2) + ' ' + 
				RIGHT('0' + CAST(@p_godzina_od AS VARCHAR), 2) + ':00:00' 
				AS DATETIME),
				CAST(CAST(DATEPART(year, @p_czas_zakonczenia) AS VARCHAR) + 
RIGHT('0' + 
				CAST(DATEPART(month, @p_czas_zakonczenia) AS VARCHAR), 2) + 
				RIGHT('0' + CAST(DATEPART(day, @p_czas_zakonczenia) 
AS VARCHAR), 2) + ' ' + 
				RIGHT('0' + CAST(DATEPART(hour, @p_czas_zakonczenia) 
AS VARCHAR), 2) + ':' +
				RIGHT('0' + CAST(DATEPART(minute, @p_czas_zakonczenia) 
AS VARCHAR), 2) + ':00' 
				AS DATETIME)
				) < 0 THEN 0
			ELSE  -- w przeciwnym wypadku rnica jest obliczana
				DATEDIFF( minute,
				CAST(CAST(DATEPART(year, @p_czas_zakonczenia) AS VARCHAR) + 
RIGHT('0' + 
				CAST(DATEPART(month, @p_czas_zakonczenia) AS VARCHAR), 2) + 
				RIGHT('0' + CAST(DATEPART(day, @p_czas_zakonczenia) 
AS VARCHAR), 2) + ' ' + 
				RIGHT('0' + CAST(@p_godzina_od AS VARCHAR), 2) + ':00:00' 
				AS DATETIME),
				CAST(CAST(DATEPART(year, @p_czas_zakonczenia) AS VARCHAR) + 
RIGHT('0' + 
				CAST(DATEPART(month, @p_czas_zakonczenia) AS VARCHAR), 2) + 
				RIGHT('0' + CAST(DATEPART(day, @p_czas_zakonczenia) 
AS VARCHAR), 2) + ' ' + 
				RIGHT('0' + CAST(DATEPART(hour, @p_czas_zakonczenia) 
AS VARCHAR), 2) + ':' +
				RIGHT('0' + CAST(DATEPART(minute, @p_czas_zakonczenia) 
AS VARCHAR), 2) + ':00' 
				AS DATETIME)					
				)
			END
		END
	END;

	-- jeli opnienie jest mniejsze od zera to ustawiamy 0
	IF @ilosc_minut <0
		SET @ilosc_minut = 0;
	
	-- obliczona warto jest zwracana
	RETURN @ilosc_minut;
END;
GO

